/*
 * Copyright (C) 2015 Daniel Uppenkamp
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.googlecode.maurersmarbles.android;

import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import com.googlecode.maurersmarbles.GameEngine;
import com.googlecode.maurersmarbles.GameState;
import com.googlecode.maurersmarbles.Screen;
import com.googlecode.maurersmarbles.TouchEvent;
import com.googlecode.maurersmarbles.drawables.Drawable;
import com.googlecode.maurersmarbles.states.IntroState;

import java.util.Collection;

/**
 * Created by Daniel Uppenkamp on 1/17/2015.
 */
public class AndroidScreen extends SurfaceView implements Screen, SurfaceHolder.Callback {

    /**
     * The screen canvas that is used to draw the drawables.
     */
    protected AndroidScreenCanvas androidScreenCanvas = new AndroidScreenCanvas();
    /**
     * The collection of drawables that are drawn on the screen.
     */
    protected Collection<Drawable> drawables;
    /**
     * The game engine that is used to drive the game.
     */
    protected GameEngine gameEngine = new GameEngine();
    /**
     * The game state.
     */
    protected GameState gameState = new GameState();
    /**
     * The surface holder.
     */
    protected SurfaceHolder surfaceHolder;

    /**
     * Creates a new AndroidScreen.
     * @param context the context
     * @param attributeSet the attribute set
     */
    public AndroidScreen(Context context, AttributeSet attributeSet) {

        super(context, attributeSet);

        // register our interest in hearing about changes to our surface
        surfaceHolder = getHolder();
        surfaceHolder.addCallback(this);

        // set the state to the intro screen
        gameEngine.setState(this, gameState, IntroState.getInstance());

    }

    protected void draw() {

        Canvas canvas = null;
        try {

            canvas = surfaceHolder.lockCanvas(null);
            synchronized (surfaceHolder) {

                // clear the screen
                if(canvas != null) {
                    canvas.drawRGB(0, 0, 0);
                }

                // set the canvas
                androidScreenCanvas.setCanvas(canvas);

                // draw all of the drawables
                if(drawables != null) {
                    for (Drawable drawable : drawables) {
                        drawable.draw(androidScreenCanvas);
                    }
                }

            }

        }
        finally {
            if (canvas != null) {
                surfaceHolder.unlockCanvasAndPost(canvas);
            }
        }

    }

    @Override
    public void draw(Collection<Drawable> drawables) {
        this.drawables = drawables;
        draw();
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        draw();
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

        gameEngine.handleResizeEvent(this, gameState, width, height);

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {

    }

    @Override
    public boolean onTouchEvent(MotionEvent e) {

        TouchEvent touchEvent = null;

        if (e.getAction() == MotionEvent.ACTION_DOWN) {
            touchEvent = new TouchEvent((int)e.getX(), (int)e.getY(), TouchEvent.TYPE_PRESSED);
        }
        else if (e.getAction() == MotionEvent.ACTION_UP) {
            touchEvent = new TouchEvent((int)e.getX(), (int)e.getY(), TouchEvent.TYPE_RELEASED);
        }

        if(touchEvent != null) {
            gameEngine.handleInputEvent(this, gameState, touchEvent);
        }

        return true;

    }

}
